//
// Created by zerax on 2020/10/27.
//

#include "camera.hh"
#include <SDL.h>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/detail/type_quat.hpp>

Camera::Camera(glm::vec3 position, glm::vec3 up, float yaw, float pitch)
    :m_position(position), m_worldUp(up), m_front(0.0f, 0.0f, -1.0f), m_zoom(45.0f), m_up(), m_right() {
    m_yaw = yaw;
    m_pitch = pitch;
    recalculateVectors();
}

glm::mat4 Camera::getMatrix() {
    return glm::lookAt(m_position, m_position + m_front, m_up);
}

void Camera::moveForward(float amount) {
    m_position += amount * m_front;
}

void Camera::moveUp(float amount) {
    m_position += amount * m_up;
}

void Camera::moveRight(float amount) {
    m_position += amount * m_right;
}

void Camera::movePitch(float amount) {
    m_pitch = glm::clamp(m_pitch + amount, -89.0f, 89.0f);
    recalculateVectors();
}

void Camera::moveYaw(float amount) {
    m_yaw += amount;
    recalculateVectors();
}

void Camera::moveZoom(float amount) {
    setZoom(m_zoom + amount);
}

void Camera::setZoom(float zoom) {
    m_zoom = glm::clamp(zoom, 1.0f, 45.0f);
    recalculateVectors();
}

void Camera::recalculateVectors() {
    auto yaw = glm::radians(m_yaw);
    auto pitch = glm::radians(m_pitch);
    auto sin_yaw = sin(yaw);
    auto cos_yaw = cos(yaw);
    auto sin_pitch = sin(pitch);
    auto cos_pitch = cos(pitch);

    m_front = glm::normalize(glm::vec3(cos_yaw * cos_pitch, sin_pitch, sin_yaw * cos_pitch));;
    m_right = glm::normalize(glm::cross(m_front, m_worldUp));
    m_up = glm::cross(m_right, m_front);
}

void Camera::moveYawPitch(float yawAmount, float pitchAmount) {
    m_yaw += yawAmount;
    m_pitch = glm::clamp(m_pitch + pitchAmount, -89.0f, 89.0f);
    recalculateVectors();
}

glm::vec3 Camera::getPosition() {
    return m_position;
}
